import { isTrue, generateCode } from "../../utils/CodeUtils"
import { getObjectValue, getEnvAttr } from "../../utils/ObjectUtils"

export function VBind(vm, vnode) {
    if(vnode.nodeType != 1) return;
    const attrs = vnode.ele.getAttributeNames()
    attrs.forEach((attr)=> {
        if(attr.startsWith("v-bind:") || attr.startsWith(":")) {
            // 设置的节点属性名称
            let attrName = attr.replace("v-bind:", "").replace(":", "")
            const attrValue = vnode.ele.getAttribute(attr)
            if(/^{[\W\w]+}$/.test(attrValue)) {
                complexVbind(vm, attrName, vnode, attrValue)
            } else {
                simpleVbind(vm, attrName, vnode, attrValue)
            }
        }
    })
}

function simpleVbind(vm, key, vnode, value) {
    const attrValue = getObjectValue(vm, value)
    if(key==='class') {
        vnode.ele.classList.add(attrValue)
    } else {
        // 给节点设置属性值
        vnode.ele.setAttribute(key, attrValue)
    }
}

/**
 * 复杂绑定
 * @param {*} key {customClass: key.a + 1 > 2}
 * @param {*} node 
 * @param {*} value 
 */
function complexVbind(vm, key, vnode, value) {
    // 移除表达式两边的花括号
    value = value.slice(1, -1)
    // 获取表达式列表
    const expressList = value.split(',')
    // 分析表达式
    const result = analyzeExpress(vm, vnode, expressList)
    vnode.ele.setAttribute(key, result)
}



function analyzeExpress(vm, vnode, expressList) {
    let result = ""
    // 获取当前表达式执行的变量
    const env = getEnvAttr(vm, vnode)
    // 生成表达式执行的变量
    const codeStr = generateCode(env)
    for(let express of expressList) {
        const site = express.indexOf(':')
        // 获取值
        const attrValue = getObjectValue(vm, express.substring(0, site))
        if(site.length === 1) {
            result+=`${attrValue} `
        } else {
            // 取出表达式计算的内容 customClass: key.a + 1 > 2 -> key.a + 1 > 2
            const expressContent = express.substring(site + 1)
            // 执行表达式
            if(isTrue(expressContent, codeStr)) {
                result+=`${attrValue}`
            }
        }
    }
    return result
}

